﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Duellum.Core;
using JpLabs.Geometry;
using System.Windows;

namespace Duellum.Game.Commands
{
	public abstract class BaseDuelCommandParamType<T> : IDuelCommandParam
	{
	    //public DuelTypeId Id { get; private set; }
	    	    
		//public BaseDuelCommandParamType(DuelTypeId id)
		//{
		//    this.Id = id;
		//}

	    public Type Type
	    {
	        get { return typeof(T); }
	    }
	    
		public virtual bool TryCoerceValue(object value, out T outValue)
		{
			outValue = default(T);
			if (!(value is T)) return false;
			
			outValue = (T)value;
			return true;
		}

	    public virtual bool IsCoercible(object value)
	    {
			T outValue;
			return TryCoerceValue(value, out outValue);
	    }
	}
	
	internal class AngleCmdParam : BaseDuelCommandParamType<double>
	{
		//public AngleCmdParam() : base(DuelCoreCommands.AngleParam)
		//{}

		public override bool TryCoerceValue(object value, out double outValue)
		{
			if (!base.TryCoerceValue(value, out outValue)) return false;
			
			outValue = CoerceAngle(outValue);
			return true;
		}
		
		static public double CoerceAngle(double angle)
		{
			//TODO: (or not) move this to a direct coersion on the Player.FaceAngle property
			
			const double TWO_PI = (2 * Math.PI);
			
			int loops = (int)Math.Floor(angle / TWO_PI);
			
			return angle - (loops * TWO_PI);
		}
	}

	internal class PointCmdParam : BaseDuelCommandParamType<Point>
	{
	}

	internal class PositionCmdParam : BaseDuelCommandParamType<PointInt>
	{
		public override bool TryCoerceValue(object value, out PointInt outValue)
		{
			if (!base.TryCoerceValue(value, out outValue)) return false;
			
			return outValue.Dimensions == 2 || outValue.Dimensions == 3;
		}
	}
}
